
//
// 110331 - AH - Created.
// 110402 - AH - Tree buildTree(File).
//

package org.soekrat.engine.pitbul.parser;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.soekrat.engine.Soekrat2Engine;
import org.soekrat.engine.forest.Tree;
import org.soekrat.engine.pit.Pit;
import org.soekrat.engine.util.CommandLineParser;

/**
 * <p>
 *   
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC) 
 */
public final class PitbulParser 
{
  private static Tree buildTree(String s)
  {
    if (s==null)
    {
      throw new NullPointerException("s");
    }
    
    try
    {
      ByteArrayInputStream baos=new ByteArrayInputStream(s.getBytes());
      return buildTree(baos);
    }
    catch (IOException _){ throw new Error(); }
  }
  
  private static Tree buildTree(File f) throws IOException
  {
    if (f==null)
    {
      throw new NullPointerException("f");
    }
    
    FileInputStream fis=null;
    try
    {
      fis=new FileInputStream(f);
      return buildTree(fis);
    }
    finally
    {
      if (fis!=null) try { fis.close(); } catch (IOException _){}
    }
  }
  
  private static Tree buildTree(InputStream is) throws IOException
  {
    if (is==null)
    {
      throw new NullPointerException("is");
    }
    
    Tree root=new Tree("root");
    
    InputStreamReader isr=new InputStreamReader(is);
    BufferedReader br=new BufferedReader(isr);    
    
    StringBuilder sb=new StringBuilder();
    
    int lnr=0;
    int cnr=0;
    
    Tree parent=root;
    
    String line=br.readLine();
    while (line!=null)
    {
      line=line.trim();
      int n=line.length();
      
      if (n>0 && line.charAt(0)!='#')
      {
        for (int i=0; i<n; i++)
        {
          int c=line.charAt(i);
          switch (c)
          {
            case '{' :
            {
              PitbulTokens tokens=getTokens(sb);
              if (tokens!=null) parent.setAttribute("pre-tokens", tokens);
              parent=parent.createChild("{");
            }
            break;
        
            case '}' :
            {
              PitbulTokens tokens=getTokens(sb);
              if (tokens!=null) parent.setAttribute("post-tokens", tokens);
              parent=parent.getParent();
            }
            break;
        
            default : sb.append((char)c);
          }
        }
      }
      line=br.readLine();
    }
    
    return root;
  }
  
  private static PitbulTokens getTokens(StringBuilder sb)
  {
    String t=sb.toString();
    t=(t==null) ? "" : t.trim();
    sb.setLength(0);
    return t.length()==0 ? null : new PitbulTokens(t);
  }
  
  public static void backend(Tree tree, Soekrat2Engine engine) throws IOException
  {
    if (tree==null)
    {
      throw new NullPointerException("tree");
    }
    if (engine==null)
    {
      throw new NullPointerException("engine");
    }
    
    int n=tree.getChildCount();
    for (int i=0; i<n; i++)
    {
      Tree curr=tree.getChild(i);
      FormParser.parseForm(curr, engine);      
    }
    
  }
  
  public static void parse(Soekrat2Engine se, File f) throws IOException
  {
    if (se==null)
    {
      throw new NullPointerException("se");
    }
    if (f==null)
    {
      throw new NullPointerException("f");
    }
    
    Tree tree=buildTree(f);
    backend(tree, se);
  }
  
  public static void parse(Soekrat2Engine se, InputStream is) throws IOException
  {
    if (se==null)
    {
      throw new NullPointerException("se");
    }
    if (is==null)
    {
      throw new NullPointerException("is");
    }
    
    Tree tree=buildTree(is);
    backend(tree, se);
  }
  
  public static void main(String[] args) 
  {
    try
    {
      CommandLineParser clp=new CommandLineParser(args);
      File inf=clp.fileValue("-in");
      
      Tree tree=null;
      
      if (inf==null)
      {  
        String input="{ aa { bb } cc }";
        tree=buildTree(input);  
      }
      else
      {
        tree=buildTree(inf);
      }
      
      Soekrat2Engine se=new Soekrat2Engine();
      
      Pit pit=new Pit();
      backend(tree, se);
      
      System.out.println("pit:");
      System.out.println(pit);
    }
    catch (IOException iox)
    {
      iox.printStackTrace();
      System.exit(-1);
    }
  }
  
}
